package org.dreamwork.tools.simulator.connector.managed;

import org.dreamwork.tools.simulator.connector.data.DummyInterface;
import org.dreamwork.tools.simulator.connector.data.WebResult;
import org.dreamwork.db.SQLite;
import org.dreamwork.util.StringUtil;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Resource
public class DummyInterfaceService {
    @Resource
    private SQLite sqlite;

    private final Map<String, DummyInterface> cache = new HashMap<> ();
    private final Object LOCKER = new byte[0];

    private final Map<String, AtomicLong> counter = Collections.synchronizedMap (new HashMap<> ());

    @PostConstruct
    public void cacheAllInterfaces () {
        List<DummyInterface> list = sqlite.get (DummyInterface.class);
        list.forEach (di -> cache.put (di.getUri (), di));
        System.out.println (cache);
    }

    public List<DummyInterface> findInterfaces (String name, int pageNo, int pageSize) {
        String sql = "SELECT * FROM dummy_interface";
        List<Object> params = new ArrayList<> ();
        if (!StringUtil.isEmpty (name)) {
            sql += " WHERE name LIKE ?";
            params.add ('%' + name.trim () + '%');
        }
        if (params.isEmpty ())
            return sqlite.list (DummyInterface.class, pageNo, pageSize, sql);
        else
            return sqlite.list (DummyInterface.class, pageNo, pageSize, sql, params.toArray (new Object[0]));
    }

    public DummyInterface findByName (String name) {
        String sql = "SELECT * FROM dummy_interface WHERE name = ?";
        return sqlite.getSingle (DummyInterface.class, sql, name);
    }

    public DummyInterface findByUri (String uri) {
        return cache.get (uri);
    }

    public WebResult save (DummyInterface di) {
        String uri = di.getUri ();
        synchronized (LOCKER) {
            if (!cache.containsKey (uri)) {
                if (sqlite.exists ("select * from dummy_interface WHERE name = ?", di.getName ())) {
                    WebResult wr = new WebResult (false, null, "名称[" + di.getName () + "]已存在");
                    wr.field = "name";
                    return wr;
                }

                if (StringUtil.isEmpty (di.getId ())) {
                    di.setId (StringUtil.uuid ());
                }
                sqlite.save (di, false);
                cache.put (di.getUri (), di);
                return new WebResult (true, di, null);
            } else {
                WebResult wr = new WebResult (false, null, "接口地址[" + di.getUri () + "]已存在");
                wr.field = "uri";
                return wr;
            }
        }
    }

    public DummyInterface getDetail (String id) {
        return sqlite.getByPK (DummyInterface.class, id);
    }

    public void delete (String id) {
        sqlite.delete (DummyInterface.class, id);
        synchronized (LOCKER) {
            DummyInterface di = null;
            for (DummyInterface d : cache.values ()) {
                if (d.getId ().equals (id)) {
                    di = d;
                    break;
                }
            }
            if (di != null) {
                cache.remove (di.getUri ());
            }
        }
    }

    public WebResult update (DummyInterface di) {
        DummyInterface c = null;
        for (DummyInterface d : cache.values ()) {
            if (d.getId ().equals (di.getId ())) {
                c = d;
                break;
            }
        }
        if (c == null) {
            WebResult wr = new WebResult (false, null, "您正在修改的接口不存在");
            wr.field = "name";
            return wr;
        }

        if (!di.getId ().equals (c.getId ())) { // uri 改重了
            WebResult result = new WebResult (false, null, "URI[" + di.getUri () + "]已存在");
            result.field = "uri";
            return result;
        }
        sqlite.update (di);
        cache.remove (c.getUri ());     // 删除老的缓存
        cache.put (di.getUri (), di);   // 同时也要更新缓存中的值
        return new WebResult (true, di, null);
    }

    public DummyInterface match (String pathInfo, Map<String, String> parsedArgs) {
        if (cache.isEmpty ()) {
            return null;
        }

        for (DummyInterface di : cache.values ()) {
            if (matches (pathInfo, di.getUri (), parsedArgs)) {
                return di;
            }
        }

        return null;
    }

    public long getSerial (String uri) {
        AtomicLong counter = this.counter.computeIfAbsent (uri, key -> new AtomicLong (1));
        return counter.getAndIncrement ();
    }

    private boolean matches (String pattern, String pathInfo, Map<String, String> parsedArgs) {
        List<String> parts = split (pathInfo);
        if (!parts.isEmpty ()) {
            List<String> tmp = split (pattern);
            if (tmp.size () != parts.size ()) {
                return false;
            }
            Map<String, String> map = new HashMap<> ();
            for (int i = 0; i < tmp.size (); i ++) {
                String name = parts.get (i);
                if (name.contains ("${")) {
                    Matcher m = PARSER.matcher (name);
                    if (m.matches ())
                        map.put (m.group (2), tmp.get (i));
                } else if (!name.equals (tmp.get (i))) {    // 任意一部分不匹配，返回false
                    return false;
                }
            }
            if (!map.isEmpty ()) {
                parsedArgs.putAll (map);
            }
            return true;
        } else {
            return pattern.equals (pathInfo);
        }
    }

    private List<String> split (String pattern) {
        String[] tmp = pattern.split ("/");
        List<String> parts = new ArrayList<> (tmp.length);
        for (String p : tmp) {
            if (!StringUtil.isEmpty (p)) {
                parts.add (p.trim ());
            }
        }
        return parts;
    }

    public static final Pattern PARSER = Pattern.compile ("^(.*?)?\\$\\{(.*?)}(.*?)?$");
}